package csel.controller.bindings;

import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;

public abstract class AbstractBindings<K, V>
{
	/**
	 * This class uses a concurrent hashmap parameterized with Integer keys and
	 * ActionEnum values, it has a default set of bindings and allows the
	 * bindings to be updated and for values to be retrieved based off of a
	 * certain key.
	 */
	private ConcurrentHashMap<K, V> bindings = new ConcurrentHashMap<K, V>();

	/**
	 * This event will take in a K and an actionEnum, this will regardless of
	 * prior us map an actionEnum to the K value. The reason there is no check
	 * is so any K can be set to any action and many Ks can be set to one
	 * action. This still enforces only a m to 1 relationship between K values
	 * and ActionEnums.
	 * 
	 * @param keyEvent
	 * @param actionEnum
	 */
	public void updateBinding(K k, V v)
	{
		bindings.put(k, v);
	}

	/**
	 * This method will return the ActionEnum mapped to a specific K value. The
	 * concurrent hashmap ensures that only one ActionEnum is mapped to a
	 * specific K value.
	 * 
	 * The method checks if they K value is a valid key in the hashmap, if it
	 * isn't it throws an IllegalStateException because someone should check if
	 * the hashmap contains the key before it attempts to retrieve the value.
	 * Thus if an attempt is made with an invalid key the program has reached an
	 * IllegalState and will throw the exception
	 * 
	 * @param keyEvent
	 * @return
	 */
	public V getEnum(K k) throws IllegalStateException
	{
		return bindings.get(k);
	}
	
	/**
	 * This returns a boolean that tells the caller of the method if the
	 * concurrent hashmap contains a key matching the given K value.
	 * 
	 * @param keyEvent
	 * @return
	 */
	public boolean containsKey(K k)
	{
		return bindings.containsKey(k);
	}
	
	/**
	 * This removes the key and the item it corresponds to from the map,
	 * never to be found again
	 *  
	 * @param k
	 */
	public void remove(V v)
	{
		Enumeration<K> keys = bindings.keys();
		while(keys.hasMoreElements()){
			K temp = keys.nextElement();
			if(v == bindings.get(temp)){
				bindings.remove(temp);
			}
		}
	}
	
	/**
	 * This returns an an enumeration of the keys in the map
	 */
	public Enumeration<K> getKeys()
	{
		return bindings.keys();
	}
	
	/**
	 * This returns an an enumeration of the values in the map
	 */
	public Enumeration<V> getValues()
	{
		return bindings.elements();
	}
}
